package com.essg.sdc.base;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * <H1>新人社員向けアルゴリズム(Java)</H1>
 *<H2>アルゴリズム（ベースクラス）</H2><br>
 *<ol>
 *	<li>社員情報(EmpData)を自動生成
 *	<li>マスタ社員情報(EmpData)を自動生成
 *	<li>各社員情報の一覧表示を行う。
 *</ol>
 *
 * @author ess0034
 */
abstract public class BaseAlgo {

	/**
	 * 社員情報を全件保管
	 */
	private List<EmpData> mEmpData;
	/**
	 * 社員情報(マスター)を全件保管
	 */
	private List<EmpData> mMEmpData;
	/**
	 * mEmpDataの現在位置
	 */
	private int mCurrent;
	/**
	 * mMEmpDataの現在位置
	 */
	private int mMCurrent;
	/**
	 * EOF用High-Value Character(12文字)
	 */
	private static char[] c =
		{Character.MAX_VALUE,Character.MAX_VALUE,Character.MAX_VALUE,Character.MAX_VALUE,Character.MAX_VALUE,Character.MAX_VALUE,
		Character.MAX_VALUE,Character.MAX_VALUE,Character.MAX_VALUE,Character.MAX_VALUE,Character.MAX_VALUE,Character.MAX_VALUE
		};
	/**
	 * EOF用High-Value String
	 */
	public static final String HIGH_VALUE = String.valueOf(c);

	/**
	 * Superクラス（BaseAlgo）のコンストラクタに指定する。<br>
	 * コンストラクタ用アルゴリズム種別
	 */
	public static enum ALGO_TYPE
	{
		/**
		 * コントロールブレークを作成する
		 */
		CONTROLBREAK,
		/**
		 * 大中小計を作成する
		 */
		CONTROLBREAKSUMUP,
		/**
		 * インナーソートを作成する
		 */
		INNERSORT,
		/**
		 * テーブルサーチを作成する
		 */
		TABLESEARCH,
		/**
		 * マッチングを作成する
		 */
		MATCHING
	};

	/**
	 * テーブルサーチ用部署・課名称配列
	 */
	public static String[] mDivsionName =
	{	"00101,第1部第1課",
		"00201,第2部第1課",
		"00301,第3部第1課",
		"00401,第4部第1課",
		"00501,第5部第1課",
		"00102,第1部第2課",
		"00202,第2部第2課",
		"00302,第3部第2課",
		"00402,第4部第2課",
		"00502,第5部第2課",
		"00103,第1部第3課",
		"00203,第2部第3課",
		"00303,第3部第3課",
		"00403,第4部第3課",
		"00503,第5部第3課",
		"00104,第1部第4課",
		"00204,第2部第4課",
		"00304,第3部第4課",
		"00404,第4部第4課",
		"00504,第5部第4課",
	};

	/**
	 * <H2>コントロールブレーク　コンストラクタ</H2>
	 * <ol>
	 * 	<li>社員情報・マスタ社員情報の作成
	 * 	<li>コントロールブレーク・大中小計：部署コード、課コードでCollectionsソート
	 * 	<li>マッチング：ESSコードでCollectionsソート
	 * </ol>
	 * @param AType アルゴリズム種別
	 */
	public BaseAlgo(ALGO_TYPE AType){
		mEmpData = new ArrayList<BaseAlgo.EmpData>();
		mMEmpData = new ArrayList<BaseAlgo.EmpData>();
		StoreEmp();
		StoreMEmp();
		if(AType == ALGO_TYPE.MATCHING){
			CollectionSortEsscd(mEmpData);
			CollectionSortEsscd(mMEmpData);
		}else{
			CollectionSort(mEmpData);
			CollectionSort(mMEmpData);
		}
		mCurrent = 0;
		mMCurrent = 0;

		System.out.println("実行Algorithm："+AType.toString());
	}


	/**
	 * <H2>アルゴリズムに従い結果を表示する。</H2><P>
	 * この部分をコーディングする。
	 */
	abstract public void ListAlgo();

	/**
	 * <H2>社員情報一覧表示</H2>
	 * 格納されている社員情報を一覧表示する。
	 */
	final protected void PrintEmp(){

		EmpData mTrEmp;
		String _detail;
		mTrEmp = nextEmp();

		while(!mTrEmp.getDivcd().equals(HIGH_VALUE)){
			_detail = mTrEmp.getDivcd() + "  " + mTrEmp.getSeccd() + "  " + mTrEmp.getEsscd() + " " + mTrEmp.getName() + String.format(" \\%1$0,3d", mTrEmp.getPay());
			System.out.println(_detail);
			mTrEmp = nextEmp();
		}

	}

	/**
	 * <H2>マスター社員情報一覧表示</H2>
	 * 格納されている社員情報(マスター)を一覧表示する。
	 */
	final protected void PrintMEmp(){

		EmpData mMEmp;
		String _detail;
		mMEmp = nextMEmp();

		while(!mMEmp.getDivcd().equals(HIGH_VALUE)){
			_detail = mMEmp.getDivcd() + "  " + mMEmp.getSeccd() + "  " + mMEmp.getEsscd() + " " + mMEmp.getName() + String.format(" \\%1$0,3d", mMEmp.getPay());
			System.out.println(_detail);
			mMEmp = nextMEmp();
		}

	}

	/**
	 * <H2>新マスター社員情報一覧表示</H2>
	 * パラメタで渡された社員情報を一覧表示する。
	 * @param pEmpdata 表示すべき社員情報
	 */
	final protected void DefaultPrintEmp(List<EmpData> pEmpdata){

		String _detail;

		for(EmpData emp : pEmpdata){
			_detail = emp.getDivcd() + "  " + emp.getSeccd() + "  " + emp.getEsscd() + " " + emp.getName() + String.format(" \\%1$0,3d", emp.getPay());
			System.out.println(_detail);
		}

	}

	/**
	 * <H2>社員情報作成</H2>
	 * 番号より「ESSコードess0001～ess0050」の社員情報を作成する。
	 * <ol>
	 * 	<li>部署コードは、001～005<br>
	 * ESSコードの５の剰余で求める。
	 * 	<li>課コードは、01～03<br>
	 * ESSコードの３の剰余で求める。
	 * 	<li>給与を20万+番号に1,000を掛けた値とする。
	 * 	<li>名前をessEmployee(番号)とする。
	 * </ol>
	 */
	final protected void StoreEmp(){

		for(int i=1; i<51; i++){
			String _esscd = String.format("ess%1$04d", i);
			String _devcd = "000";
			String _seccd = "00";

			switch (i%5) {
			case 0:
				_devcd = String.format("%1$03d", 5);
				break;
			default:
				_devcd = String.format("%1$03d", i%5);
				break;
			}

			switch (i%3) {
			case 0:
				_seccd = String.format("%1$02d", 3);
				break;
			default:
				_seccd = String.format("%1$02d", i%3);
				break;
			}

			String _name = "essEmployee(" + String.format("%1$02d",i) +")";
			int _pay = (i*1000)+200000;

			EmpData _data = new EmpData();
			_data.setEsscd(_esscd);
			_data.setDivcd(_devcd);
			_data.setSeccd(_seccd);
			_data.setName(_name);
			_data.setPay(_pay);

			mEmpData.add(_data);
		}

	}


	/**
	 * <H2>マスタ社員情報作成</H2>
	 * 番号より「ESSコードess0001～ess0100」の社員情報を４飛びに作成する。<br>
	 * マスターの変更内容は
	 * <ol>
	 * 	<li>給与に(20万+番号*1,000)*10％を設定する。
	 * </ol>
	 */
	final protected void StoreMEmp(){

		for(int i=1; i < 101; i+=4){

			String _esscd = String.format("ess%1$04d", i);
			String _devcd = "000";
			String _seccd = "00";

			switch (i%5) {
			case 0:
				_devcd = String.format("%1$03d", 5);
				break;
			default:
				_devcd = String.format("%1$03d", i%5);
				break;
			}

			switch (i%3) {
			case 0:
				_seccd = String.format("%1$02d", 3);
				break;
			default:
				_seccd = String.format("%1$02d", i%3);
				break;
			}

			String _name = "essEmployee(" + String.format("%1$02d",i) +")";

			int _pay = (int)(((i*1000)+200000) * 0.1);

			EmpData _data = new EmpData();
			_data.setEsscd(_esscd);
			_data.setDivcd(_devcd);
			_data.setSeccd(_seccd);
			_data.setName(_name);
			_data.setPay(_pay);

			mMEmpData.add(_data);
		}

	}


	/**
	 * <H2>Collectionsによるソートを実施</H2>
	 * ソートキーは「部署コード」+「課コード」で昇順としている。
	 * @param pEmpData ソートすべき社員情報
	 */
	final protected void CollectionSort(List<EmpData> pEmpData){

		Collections.sort(pEmpData, new Comparator<EmpData>() {
			@Override
			public int compare(EmpData o1, EmpData o2) {

				String _o1 = o1.getDivcd() + o1.getSeccd();
				String _o2 = o2.getDivcd() + o2.getSeccd();
				return (_o1).compareTo(_o2);
			}
		});

	}

	/**
	 * <H2>Collections(ESSコード)によるソートを実施</H2>
	 * ソートキーは「ESSコード」で昇順としている。
	 * @param pEmpData ソートすべき社員情報
	 */
	final protected void CollectionSortEsscd(List<EmpData> pEmpData){

		Collections.sort(pEmpData, new Comparator<EmpData>() {
			@Override
			public int compare(EmpData o1, EmpData o2) {

				String _o1 = o1.getEsscd();
				String _o2 = o2.getEsscd();
				return (_o1).compareTo(_o2);
			}
		});

	}

	/**
	 * <H2>社員情報の読込</H2>
	 * mEmpDataの(mCurrent)読込位置より次の社員情報を読み込む<br>
	 * EOFになった場合は、HIGH_VALUEをESSCD,部署コード,課コードに設定する。
	 * @return EmpData（社員情報）
	 */
	final protected EmpData nextEmp(){
		mCurrent += 1;
		if(mCurrent > mEmpData.size()){
			EmpData _result = new EmpData();
			_result.setDivcd(HIGH_VALUE);
			_result.setSeccd(HIGH_VALUE);
			_result.setEsscd(HIGH_VALUE);
			return _result;
		}
		return mEmpData.get(mCurrent-1);
	}

	/**
	 * <H2>マスタ社員情報の読込</H2>
	 * mMEmpDataの(mMCurrent)読込位置より次の社員情報を読み込む<br>
	 * EOFになった場合は、HIGH_VALUEをESSCD,部署コード,課コードに設定する。
	 * @return EmpData（マスタ社員情報）
	 */
	final protected EmpData nextMEmp(){
		mMCurrent += 1;
		if(mMCurrent > mMEmpData.size()){
			EmpData _result = new EmpData();
			_result.setDivcd(HIGH_VALUE);
			_result.setSeccd(HIGH_VALUE);
			_result.setEsscd(HIGH_VALUE);
			return _result;
		}
		return mMEmpData.get(mMCurrent-1);
	}

	/**
	 * <H2>部署・課名称の一覧表示</H2>
	 *
	 */
	final protected void printDivSecName(){
		String _detail;
		for(int i=0;i<mDivsionName.length;i++){
			_detail = "部署/課名称("+ String.format("%1$02d",i+1) + "):" + mDivsionName[i];
			System.out.println(_detail);
		}
	}

	/**
	 * <H1>社員情報</H1>
	 *
	 */
	public class EmpData{

		/**
		 * ESSコード
		 */
		private String esscd;
		/**
		 * 部署コード
		 */
		private String divcd;
		/**
		 * 課コード
		 */
		private String seccd;
		/**
		 * 社員名称
		 */
		private String name;
		/**
		 * 社員給与
		 */
		private int pay;

		public EmpData(){
			esscd = "";
			divcd = "";
			seccd = "";
			name = "";
			pay = 0;
		}

		public String getEsscd() {
			return esscd;
		}
		public void setEsscd(String esscd) {
			this.esscd = esscd;
		}
		public String getDivcd() {
			return divcd;
		}
		public void setDivcd(String divcd) {
			this.divcd = divcd;
		}
		public String getSeccd() {
			return seccd;
		}
		public void setSeccd(String seccd) {
			this.seccd = seccd;
		}
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public int getPay() {
			return pay;
		}
		public void setPay(int pay) {
			this.pay = pay;
		}

	}

}
